package main

import (
	"context"
	"fmt"
	"mysql-read-file/blockworkpool"
	"time"
)

func main() {
	//将 查询/更新数据库 拆分为两个task, 便于根据两者耗时调整对应线程池大小
	/*err := DataSync(context.Background())
	if err != nil {
		fmt.Println(err)
	}*/
	testBatch()
}

//分批次处理
func testBatch() {
	batchSize := 100
	notifyNameVOList := []interface{}{"1", nil, "3"}
	tmpNotifyCnt := 0
	totalNotifyCnt := len(notifyNameVOList)
	var notifyNameList []string
	for _, notifyNameVO := range notifyNameVOList {
		//注意先累加再跳过
		tmpNotifyCnt++

		if notifyNameVO == nil {
			continue
		}

		//收集批次通知信息, 计数
		notifyNameList = append(notifyNameList, notifyNameVO.(string))

		//X人同一批次
		if len(notifyNameList) >= batchSize || totalNotifyCnt == tmpNotifyCnt {
			fmt.Println(notifyNameList)
			//重置
			notifyNameList = []string{}
		}
	}
}

type DataQueryTask struct {
	ctx  context.Context
	list []int
	page int
}

// Run 查询完成后, 放入
func (task *DataQueryTask) Run() {
	for _, item := range task.list {
		time.Sleep(500 * time.Millisecond)
		fmt.Println("query from http result=", item, "\t", time.Now())
		updateTask := &DataUpdateTask{
			num: item + 1000,
		}
		dataSyncPoolMgr.AddTaskToUpdatePool(updateTask.Run)
	}
}

type DataUpdateTask struct {
	num int
}

func (task *DataUpdateTask) Run() {
	time.Sleep(1000 * time.Millisecond)
	fmt.Println("update to DB result=", task.num, "\t", time.Now())
}

// DataSync 同步数据(1.查询 2.更新DB)
func DataSync(ctx context.Context) error {
	dataSyncPoolMgr = CreateDataSyncPoolMgr(ctx)
	startIndex := 0

	tmp := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	total := len(tmp)
	for {
		var end int
		if startIndex+PageSize >= total {
			end = total
		} else {
			end = startIndex + PageSize
		}
		task := &DataQueryTask{
			list: tmp[startIndex:end],
			ctx:  ctx,
		}
		dataSyncPoolMgr.AddTaskToQueryPool(task.Run)
		//dataSyncPoolMgr.AddRunTaskToQueryPool(task)

		startIndex += PageSize
		if startIndex >= total {
			break
		}
	}
	dataSyncPoolMgr.Wait()
	return nil
}

// DataSyncPoolMgr 同步协程结构体
type DataSyncPoolMgr struct {
	poolMgr    *blockworkpool.WorkPoolMgr
	queryPool  string //查询http请求的线程池名称
	updatePool string //查询http请求的结果,存入DB的线程池名称
}

const PageSize = 5

var dataSyncPoolMgr *DataSyncPoolMgr

// CreateDataSyncPoolMgr 创建 coroutine pool 管理
func CreateDataSyncPoolMgr(ctx context.Context) *DataSyncPoolMgr {
	pool := &DataSyncPoolMgr{
		poolMgr:    blockworkpool.NewWorkPoolMgr(ctx),
		queryPool:  "queryPool",
		updatePool: "updatePool",
	}
	//注意 Pool 名字要与方法对应上, 不然无法加入任务队列
	if pool.queryPool == "" || pool.updatePool == "" {
		fmt.Println("Pool name is empty!")
	}
	pool.poolMgr.AddPool(pool.updatePool, 3, 6)
	pool.poolMgr.AddPool(pool.queryPool, 2, 4)
	return pool
}

// go wait
func (mgr *DataSyncPoolMgr) GoWait(task blockworkpool.Task) {
	mgr.poolMgr.GoWaitTask(task)
}

// 填加任务进 module pool
func (mgr *DataSyncPoolMgr) AddRunTaskToUpdatePool(task blockworkpool.RunTask) {
	mgr.poolMgr.RunTaskEnqueue(mgr.updatePool, task)
}

// 添加任务
func (mgr *DataSyncPoolMgr) AddRunTaskToQueryPool(task blockworkpool.RunTask) {
	mgr.poolMgr.RunTaskEnqueue(mgr.queryPool, task)
}

// 添加任务
func (mgr *DataSyncPoolMgr) AddTaskToUpdatePool(task blockworkpool.Task) {
	mgr.poolMgr.RunTaskEnqueue(mgr.updatePool, task)
}

// 添加任务
func (mgr *DataSyncPoolMgr) AddTaskToQueryPool(task blockworkpool.Task) {
	mgr.poolMgr.RunTaskEnqueue(mgr.queryPool, task)
}

// 等待任务执行
func (mgr *DataSyncPoolMgr) Wait() {
	mgr.poolMgr.Wait()
}
